package com.google.code.p.restrpc.mon.web;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;

/**
 * @author dz
 */
public abstract class AbstractServiceDispatcher implements ServiceDispatcher {
    
    private static final Log logger = LogFactory.getLog(AbstractServiceDispatcher.class);
    
    private static SerializeConfig mapping = new SerializeConfig();
    
    static {
        mapping.put(Date.class,
                    new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
    }
    
    /**
     * 
     */
    public String dispatch(String methodName, Map parameters) {
        if (StringUtils.isEmpty(methodName)) {
            return failedJson("Invalid request,the request is empty!");
        }
        
        try {
            Method method = getServiceObject().getClass().getMethod(methodName,
                                                                    Map.class);
            Object executedResult = method.invoke(getServiceObject(),
                                                  parameters);
            return succeedJson(executedResult);
        }
        catch (SecurityException e) {
            logger.debug(e,e);
            return failedJson("No permission of request '" + methodName + "'");
        }
        catch (IllegalArgumentException e) {
            logger.debug(e,e);
            return failedJson("Invalid request '" + methodName
                              + "',please check the request parameter!");
        }
        catch (NoSuchMethodException e) {
            logger.debug(e,e);
            return failedJson("'" + methodName + "' not exists!");
        }
        catch (IllegalAccessException e) {
            logger.debug(e,e);
            return failedJson("Invalid request '" + methodName + "'");
        }
        catch (InvocationTargetException e) {
            logger.debug(e,e);
            return failedJson("Request '" + methodName
                              + "' failed!The error message is '"
                              + e.getTargetException().getMessage()
                              + "'");
        }
        catch (Exception e) {
            logger.debug(e,e);
            return failedJson("Invalid request '" + methodName
                              + "'!the error message is '"
                              + e.getMessage()
                              + "'");
        }
    }
    
    public abstract Object getServiceObject();
    
    static String toJsonString(Object object) {
        return JSON.toJSONString(object, mapping);
    }
    
    static Map<String, Object> succeedMap(Object obj) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.TRUE);
        if (null != obj) {
            result.put("data", obj);
        }
        return result;
    }
    
    static Map<String, Object> failedMap(String message) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.FALSE);
        result.put("message", message);
        return result;
    }
    
    static Map<String, Object> failedMap(String message,
                                         String code,
                                         String field) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.FALSE);
        result.put("message", message);
        Map<String, Object> errorDetail = new HashMap<String, Object>();
        errorDetail.put("code", code);
        errorDetail.put("field", field);
        result.put("error", errorDetail);
        return result;
    }
    
    static String succeedJson(Object obj) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.TRUE);
        if (null != obj) {
            result.put("data", obj);
        }
        return toJsonString(result);
    }
    
    static String failedJson(String message) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.FALSE);
        result.put("message", message);
        return toJsonString(result);
    }
    
}
